﻿using System;
using Microsoft.Practices.ServiceLocation;

namespace Microsoft.Services.Clab.UI.Mvvmc
{
    public class ViewHelper
    {
        public static void OnControlInitialized<TView>(TView view, bool designMode) where TView : IView
        {
            if (view.State < ViewState.Initialized && !designMode)
            {
                ViewHelper.TryViewFirstInitialization(view);
            }
        }

        public static void OnControlLoaded<TView>(TView view) where TView : IView
        {
            view.State = ViewState.Loaded;
        }

        public static void TryViewFirstInitialization<TView>(TView view) where TView : IView
        {
            if (view == null)
            {
                throw new ArgumentNullException("view");
            }

            if (view.ViewModel != null)
            {
                return; // already initialized
            }

            var attribute = Attribute.GetCustomAttribute(view.GetType(), typeof(ViewFirstInitializationAttribute)) as ViewFirstInitializationAttribute;
            if (attribute != null && !string.IsNullOrEmpty(attribute.ControllerLogicalName))
            {
                if (!attribute.Async)
                {
                    ServiceLocator.Current.GetInstance<IControllerFactory>().CreateControllerSync(
                        attribute.ControllerLogicalName,
                        initParameters: new KeyValueCollection() { { "__VIEW_INSTANCE__", view } },
                        onException: ex => { throw ex; });
                }
                else
                {
                    ServiceLocator.Current.GetInstance<IControllerFactory>().CreateController(
                        attribute.ControllerLogicalName,
                        initParameters: new KeyValueCollection() { { "__VIEW_INSTANCE__", view } },
                        onException: ex => { throw ex; });
                }
            }
        }

        public static void Dispose<TView>(TView view, Action<TView> disposeCore) where TView : IView
        {
            if (view.State < ViewState.Disposing)
            {
                try
                {
                    view.State = ViewState.Disposing;

                    if (disposeCore != null)
                        disposeCore(view);
                }
                finally
                {
                    view.State = ViewState.Disposed;
                }
            }
            GC.SuppressFinalize(view);
        }
    }
}